package com.linq.cool.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.linq.cool.common.constants.UserConstants;
import com.linq.cool.common.core.exception.BusinessException;
import com.linq.cool.system.domain.SysDict;
import com.linq.cool.system.domain.SysDictItem;
import com.linq.cool.system.dto.SysDictQueryDTO;
import com.linq.cool.system.mapper.SysDictMapper;
import com.linq.cool.system.service.SysDictItemService;
import com.linq.cool.system.service.SysDictService;
import com.linq.cool.system.utils.DictUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * @Author: yqlin
 * @Date: 2021/1/23 00:35
 * @Description:
 * @Version: 1.0.0
 */

@Service
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements SysDictService {
    @Autowired
    private SysDictItemService sysDictItemService;


    /**
     * 项目启动时，初始化字典到缓存
     */
    @PostConstruct
    public void initDict() {
        List<SysDict> dictList = this.list();
        // 查询出所有字典类型下的字典数据 存入到redis
        for (SysDict dict : dictList) {
            List<SysDictItem> dictItems = sysDictItemService.list(new LambdaQueryWrapper<SysDictItem>()
                                                                          .eq(SysDictItem::getStatus, UserConstants.StateEnum.STATUS_NORMAL.getCode())
                                                                          .eq(SysDictItem::getDictId, dict.getId())
                                                                          .orderByAsc(SysDictItem::getSort)
            );
            DictUtils.setDictCache(dict.getCode(), dictItems);
        }
    }


    @Override
    public IPage<SysDict> listByPage(IPage<SysDict> page, SysDictQueryDTO dto) {
        return baseMapper.selectPage(page, new LambdaQueryWrapper<SysDict>()
                .like(StringUtils.checkValNotNull(dto.getName()), SysDict::getName, dto.getName())
                .like(StringUtils.checkValNotNull(dto.getCode()), SysDict::getCode, dto.getCode())
                .eq(StringUtils.checkValNotNull(dto.getStatus()), SysDict::getStatus, dto.getStatus())
                .between(StringUtils.checkValNotNull(dto.getParams().get("beginTime")), SysDict::getGmtCreate, dto.getParams().get("beginTime"), dto.getParams().get("endTime"))
        );
    }

    @Override
    public boolean checkCodeUnique(SysDict dict) {
        // 判断传入的是否是空(新增或者更细) 新增的时候id dictId=-1  更新就是原来的
        Long dictId = null == dict.getId() ? -1L : dict.getId();
        SysDict one = this.getOne(new LambdaQueryWrapper<SysDict>()
                                          .eq(SysDict::getCode, dict.getCode()));
        // 判断id是否一致 不一致就代表 唯一 false
        return null != one && !dictId.equals(one.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveDict(SysDict dict) {
        if (this.save(dict)) {
            // 清空redis中存放的缓存
            DictUtils.clearDictCache();
            return true;
        }
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateDict(SysDict dict) {
        if (this.updateById(dict)) {
            DictUtils.clearDictCache();
            return true;
        }
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteByIds(List<Long> dictIds) {
        for (Long dictId : dictIds) {
            SysDict dict = this.getById(dictId);
            // 判断字典数据dictItem中已经在 使用了
            int count = sysDictItemService.count(new LambdaQueryWrapper<SysDictItem>().eq(SysDictItem::getDictId, dict.getId()));
            if (count > 0) {
                throw new BusinessException(String.format("%1$s已分配,不能删除", dict.getName()));
            }
        }
        if (this.removeByIds(dictIds)) {
            // 清空redis中存放的数据
            DictUtils.clearDictCache();
            return true;
        }
        return false;
    }

    @Override
    public void clearCache() {
        DictUtils.clearDictCache();
    }

    @Override
    public List<SysDictItem> listDictItemsByDictCode(String dictCode) {
        // 从缓存中读出
        List<SysDictItem> dictItems = DictUtils.getDictCache(dictCode);
        if (CollectionUtils.isNotEmpty(dictItems)) {
            return dictItems;
        }
        // 根据dictCode查询出当前Dict
        SysDict curDict = this.getOne(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, dictCode));
        if (curDict != null) {
            // 根据dictId查询出当前字典数据列表
            List<SysDictItem> curDictItems = sysDictItemService.list(new LambdaQueryWrapper<SysDictItem>()
                                                                             .eq(SysDictItem::getDictId, curDict.getId()));
            if (CollectionUtils.isNotEmpty(curDictItems)) {
                DictUtils.setDictCache(dictCode, curDictItems);
                return dictItems;
            }
        }
        return null;
    }

    @Override
    public List<SysDict> listByParams(SysDict dict) {
        return this.list(this.getLambdaQueryWrapper(dict));
    }

    private LambdaQueryWrapper<SysDict> getLambdaQueryWrapper(SysDict dict) {
        return new LambdaQueryWrapper<SysDict>()
                .like(StringUtils.checkValNotNull(dict.getName()), SysDict::getName, dict.getName())
                .eq(StringUtils.checkValNotNull(dict.getStatus()), SysDict::getName, dict.getStatus())
                .like(StringUtils.checkValNotNull(dict.getCode()), SysDict::getName, dict.getCode())
                ;
    }
}
